#include "cache.h"

void cache::compute(void)
{
  while (true) {

    wait();

    if (cs.read() == SC_LOGIC_1) { 

      _tag    = addr.read()(31, 9).to_uint();
      _index  = addr.read()( 8, 4).to_uint();
      _offset = addr.read()( 3, 0).to_uint() * 8;

      /* READ */
      if (rw.read() == SC_LOGIC_0) {

        rdy.write(SC_LOGIC_0);
        wait(10, SC_NS); // reading one word
        rdy.write(SC_LOGIC_1);

        tout.write(_tab[_index]);

        dout0.write(_mem[_index]( 31,  0));
        dout1.write(_mem[_index]( 63, 32));
        dout2.write(_mem[_index]( 95, 64));
        dout3.write(_mem[_index](127, 96));

        /* hit */
        if (_tab[_index](24, 2) == _tag &&
            _tab[_index][1] == SC_LOGIC_1)
          hit.write(SC_LOGIC_1);

        /* [compulsory] miss */
        else
          hit.write(SC_LOGIC_0);


      /* WRITE */
      } else if (rw.read() == SC_LOGIC_1) {

        /* from CPU */
        if (block == SC_LOGIC_1) {

          rdy.write(SC_LOGIC_0);
          wait(10, SC_NS); // writing one word
          rdy.write(SC_LOGIC_1);

          switch (addr.read()(3, 0).to_uint()) {
            case 0x4:
              _mem[_index].range(_OFFEND, _offset) = din1.read();
              break;

            case 0x8:
              _mem[_index].range(_OFFEND, _offset) = din2.read();
              break;

            case 0xC:
              _mem[_index].range(_OFFEND, _offset) = din3.read();
              break;

            case 0x0:
            default:
              _mem[_index].range(_OFFEND, _offset) = din0.read();
          }

        /* from MH */
        } else if (block == SC_LOGIC_0) {
          rdy.write(SC_LOGIC_0);
          wait(40, SC_NS); // writing four words
          rdy.write(SC_LOGIC_1);

          _mem[_index].range( 31,  0) = din0.read();
          _mem[_index].range( 63, 32) = din1.read();
          _mem[_index].range( 95, 64) = din2.read();
          _mem[_index].range(127, 96) = din3.read();
        }

        // write table [tag, valid]
        _tab[_index].range(24, 2) = _tag;
        _tab[_index][1] = set_v.read();
        _tab[_index][0] = din_src.read();

      }

    }

  }
}
